#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/stat.h>
#include <atomic>
#include <fstream>
#include <sys/time.h>
#include <vector>
#include <boost/algorithm/string.hpp>

namespace ns_util
{
    std::string temp_path = "./temp/";

    class PathUtil
    {
    private:
        //
        static std::string Addsuffix(const std::string &file_name, const std::string suffix)
        {
            std::string name = temp_path;
            name += file_name;
            name += suffix;
            return name;
        }

    public:
        //.cpp
        // 1234 ————> ./temp/1234.cpp
        static std::string CPP(const std::string &file_name)
        {
            return Addsuffix(file_name, ".cpp");
        }

        //.exe
        static std::string EXE(const std::string &file_name)
        {
            return Addsuffix(file_name, ".exe");
        }

        //.stderror
        static std::string Stderror(const std::string &file_name)
        {
            return Addsuffix(file_name, ".stderror");
        }

        //.Stdin
        static std::string Stdin(const std::string &file_name)
        {
            return Addsuffix(file_name,".compile_in");
        }
        //.Stdout
        static std::string Stdout(const std::string &file_name)
        {
            return Addsuffix(file_name,".compile_out");
        }
        //.Run_error
        static std::string Run_error(const std::string &file_name)
        {
            return Addsuffix(file_name,".Run_error");
        }

    };

    class FileUtil
    {
    public:
        static bool FILE_IS_EXISTS(const std::string &file_name)
        {
            struct stat file_stat;
            if(stat(file_name.c_str(),&file_stat) == 0)
            {
                return true;
            }
            return false;
            
        }

        static std::string CreatFileName()
        {
            struct timeval timeval;
            gettimeofday(&timeval,nullptr);
            std::string ms = std::to_string(timeval.tv_sec * 1000 + timeval.tv_usec / 1000);

            //+static保存在静态区，就不会每次访问都初始化
            static std::atomic<int> add(0);
            add++;

            std::string file_name = ms + "_"  + std::to_string(add);
            return file_name;
        }

        static bool WriteFile(const std::string& file_name,const std::string& code)
        {
            std::ofstream out(file_name);
            if(!out.is_open())
            {
                return false;
            }
            //打开成功，写入
            out.write(code.c_str(),code.size());
            out.close();
            return true;
            
        }

        static bool ReadFile(const std::string& file_name,std::string* str,bool remain/*还需要一些参数*/)
        {
            //每次读前，清空str，因为只定义了一个str
            (*str).clear();
            std::ifstream in(file_name);
             if(!in.is_open())
            {
                return false;
            }
            //打开成功，读取
            std::string line;
            //getline不会读分隔符 "\n"，这个我们得按情况决定
            //getline内部重载了强转，所以返回值可被while判断
            while(std::getline(in,line))
            {
                (*str) += line;
                (*str) += (remain ? "\n" : "");
            }
            in.close();
            return true;
        }
    };

    class StringUtil
    {
    public:
        static void SplitString(const std::string& str,std::vector<std::string>* out,const std::string sep)
        {
            //例子:1:hh::::::gg
            //第四个参数——>on表示hh和gg中间的多个sep会被压缩
            boost::split(*out,str,boost::is_any_of(sep),boost::algorithm::token_compress_on);
        }
    };
}